package org.zjt.java.demo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.zjt.java.demo.config.security.TokenUtils;
import org.zjt.java.demo.vo.RestResultMsg;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Optional;

/**
 * Created by Administrator on 2017/3/11.
 */
@Controller
@RequestMapping("/auth")
public class SecurityController {

    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityController.class);

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private TokenUtils tokenUtils;

    @Value("${merchant.token.header}")
    private String tokenHeader;


    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String createAuthenticationToken(@RequestParam String name,
                                            @RequestParam String password,
                                            @RequestParam(value = "validCode", required = false) String validCode,
                                            HttpServletRequest request, HttpServletResponse response) {
        final UserDetails userDetails = userDetailsService.loadUserByUsername(name);
        try {
            if (userDetails == null)
                throw new UsernameNotFoundException("用户名或者密码错误");
            if (StringUtils.isEmpty(password) || StringUtils.isEmpty(name))
                throw new UsernameNotFoundException("用户名或者密码错误");
            if (!password.equals(userDetails.getPassword()))
                throw new BadCredentialsException("用户名或者密码错误");
        } catch (UsernameNotFoundException | BadCredentialsException e) {
            LOGGER.error("登录异常信息:{}", e);
            return "redirect:/login";
        }
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        LOGGER.info("authenticated user " + name + ", setting security context");
        SecurityContextHolder.getContext().setAuthentication(authentication);
        final String token = this.tokenUtils.generateToken(userDetails);
        Cookie cookie = new Cookie(tokenHeader, token);
        cookie.setPath("/");
        response.addCookie(cookie);
        return "redirect:/home";
    }


    @RequestMapping(value = "/refreshToken", method = RequestMethod.GET)
    @ResponseBody
    public RestResultMsg<String> refreshToken(HttpServletRequest request, HttpServletResponse response) {
        Cookie[] cookies = request.getCookies();//这样便可以获取一个cookie数组
        if (cookies != null) {
            Optional<Cookie> any = Arrays.stream(cookies).filter(i -> i != null).filter(i -> i.getName().equals(this.tokenHeader)).findAny();
            if (any.isPresent()) {
                String authToken = any.get().getValue();
                if (StringUtils.isEmpty(authToken))
                    return new RestResultMsg<String>(HttpStatus.NOT_MODIFIED, HttpStatus.NOT_MODIFIED.name(), false);
                String token = this.tokenUtils.refreshToken(authToken);
                Cookie cookie = new Cookie(tokenHeader, token);
                cookie.setPath("/");
                response.addCookie(cookie);
            }
        }
        return new RestResultMsg<String>(HttpStatus.OK, HttpStatus.OK.name(), true);
    }


    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logoutPage(HttpServletRequest request, HttpServletResponse response) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        Cookie cookie = new Cookie(tokenHeader, "");
        cookie.setPath("/");
        response.addCookie(cookie);
        return "redirect:/login";
    }

}
